package org.github.rayson517.easyplatform.common.web.base.controller;

import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.codec.digest.DigestUtils;
import org.github.rayson517.easyplatform.common.web.annotation.Field2Column;
import org.github.rayson517.easyplatform.common.web.base.entity.BaseModel;
import org.github.rayson517.easyplatform.common.web.base.entity.PagingandEntity;
import org.github.rayson517.easyplatform.common.web.constants.RequestParamConstants;
import org.github.rayson517.easyplatform.common.web.jwt.JwtUtil;
import org.github.rayson517.easyplatform.common.web.support.HttpKit;
import org.github.rayson517.easyplatform.common.web.toolbox.AjaxResult;
import org.github.rayson517.easyplatform.common.web.util.StrUtil;
import org.github.rayson517.easyplatform.common.web.util.ThreadLocalUtil;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.baomidou.mybatisplus.mapper.EntityWrapper;

import io.jsonwebtoken.Claims;

/**
 * 
 * <p>Title: BaseController</p>
 * <p>Description: </p>
 * @author rayson517
 * @date 2018-03-30 13:49
 * @version 1.0
 */
public class BaseController {
    protected static String SUCCESS = "SUCCESS";
    protected static String ERROR = "ERROR";

    protected static String REDIRECT = "redirect:";
    protected static String FORWARD = "forward:";
   
   protected HttpServletRequest getHttpServletRequest() {
       return HttpKit.getRequest();
   }

   protected HttpServletResponse getHttpServletResponse() {
       return HttpKit.getResponse();
   }

   protected HttpSession getSession() {
       return HttpKit.getRequest().getSession();
   }

   protected HttpSession getSession(Boolean flag) {
       return HttpKit.getRequest().getSession(flag);
   }

   protected String getPara(String name) {
       return HttpKit.getRequest().getParameter(name);
   }

   protected void setAttr(String name, Object value) {
       HttpKit.getRequest().setAttribute(name, value);
   }
   
/** ============================     ajax  start  =================================================  */
   
   /**   
    * 返回ajaxresult
    * @param data
    * @return AjaxResult
   */
   public AjaxResult json(Object data) {
       return new AjaxResult().success(data);
   }
   
   /**   
    * 返回ajaxresult
    * @param data
    * @param message
    * @return AjaxResult
   */
   public AjaxResult json(Object data, String message) {
       return json(data).setMessage(message);
   }
   
   
   /**   
    * 返回ajaxresult
    * @param data
    * @param message
    * @param code
    * @return AjaxResult
   */
   public AjaxResult json(Object data, String message, String code) {
       return json(data, message).setCode(code);
   }
   
   /**   
    * 返回ajaxresult
    * @param message
    * @return AjaxResult
   */
   public AjaxResult success(String message) {
       return new AjaxResult().addSuccess(message);
   }
   
   /**   
    * 返回ajaxresult
    * @param message
    * @return AjaxResult
   */
   public AjaxResult error(String message) {
       return new AjaxResult().addError(message);
   }
   
   /**   
    * 参数错误返回ajaxresult
    * @param message
    * @return AjaxResult
   */
   public AjaxResult paramsError(String message) {
       return new AjaxResult().addParamError(message);
   }
   
   /**   
    * 返回ajaxresult
    * @param message
    * @return AjaxResult
   */
/*  public AjaxResult warn(String message) {
       return new AjaxResult().addWarn(message);
   }*/
   
   /**   
    * 返回ajaxresult
    * @param message
    * @return AjaxResult
   */
   public AjaxResult fail(String message) {
       return new AjaxResult().addFail(message);
   }
   /** ============================     ajax  end  =================================================  */
   
   
    /**
    * 删除cookie
    */
   protected void deleteCookieByName(String cookieName) {
       Cookie[] cookies = this.getHttpServletRequest().getCookies();
       for (Cookie cookie : cookies) {
           if (cookie.getName().equals(cookieName)) {
               Cookie temp = new Cookie(cookie.getName(), "");
               temp.setMaxAge(0);
               this.getHttpServletResponse().addCookie(temp);
           }
       }
   }
   
   /**
    * 直接响应数据
    * @param resultMsg
    * @throws IOException
    */
   protected void response(HttpServletResponse response, String resultMsg) throws IOException {
       PrintWriter print = response.getWriter();
       try{
           print.write(resultMsg);  
           print.flush();  
       }finally{
           print.close();
       }
       
       return;
   }
   
   protected String validatedError(BindingResult result) {
       List<AjaxResult> errorList = new ArrayList<AjaxResult>();
       for (FieldError error : result.getFieldErrors()) {
           AjaxResult errorResult = new AjaxResult();
           errorResult.setCode(error.getField());
           errorResult.setMessage(error.getDefaultMessage());
           errorList.add(errorResult);
       }
       return JSONObject.toJSONString(errorList);
   }
   
   /**
    * 验证签名
    * @param request
    * @return
    */
   public Boolean isSigned(HttpServletRequest request){
       String signature = request.getParameter(RequestParamConstants.SIGN_PARAM_NAME);
       if (signature == null || signature.isEmpty()) {
           return false;
       }
       
       String secret_key = request.getParameter(RequestParamConstants.SECRET_KEY);
       if (secret_key == null || secret_key.isEmpty()) {
           return false;
       }
       
       Map<String, String[]> params = request.getParameterMap();
       Map<String, String[]> map = new TreeMap<>();
       map.putAll(params);
       map.remove(RequestParamConstants.SIGN_PARAM_NAME);

       StringBuilder builder = new StringBuilder();
       for (Map.Entry<String, String[]> entry : map.entrySet()) {
           if (entry.getValue() == null) {
               continue;
           }
           builder.append(entry.getKey()).append('=');
           String[] value = entry.getValue();
           if (value.length == 1) {
               builder.append(value[0]).append('&');
               continue;
           }
           for (int i = 0; i < value.length; i++) {
               builder.append(value[i]).append(',');
           }
           builder.deleteCharAt(builder.length() - 1).append('&');
       }
       
       builder.append("secret_key").append('=').append(secret_key);
       return signature.equals(DigestUtils.md5Hex(builder.toString()));
   }
   
   /**
    * 
    * 将PagingandEntity中的查询参数注入EntityWrapper并返回(用于单表查询)
    * @param pagingandEntity 查询相关参数
    * @return  装入了查询参数的EntityWrapper
    * @throws Exception 
    */
   protected <E extends BaseModel<E>>EntityWrapper<E> getEntityWrapper(PagingandEntity<E> pagingandEntity,E entity) throws Exception{
	   EntityWrapper<E> entityWrapper=new EntityWrapper<E>();
	   String order=pagingandEntity.getOrder();
       String sort=pagingandEntity.getSort();
       if(order!=null&&sort!=null) {
    	   entityWrapper.orderBy(entity.getColumn(sort),order.equals("asc"));
       }
       String start=pagingandEntity.getStartTime();
       String end=pagingandEntity.getEndTime();
       String between=pagingandEntity.getBetween();
       if(start!=null&&end!=null&&between!=null) {
    	   entityWrapper.between(entity.getColumn(between), start, end);
       }
	   if((entity=pagingandEntity.getEq())!=null) {
		   injectionEntityWrapper(entity,entityWrapper,"eq");
	   }
	   if((entity=pagingandEntity.getNe())!=null) {
		   injectionEntityWrapper(entity,entityWrapper,"ne");
	   }
	   if((entity=pagingandEntity.getLike())!=null) {
		   injectionEntityWrapper(entity,entityWrapper,"like");
	   }
	   if((entity=pagingandEntity.getNotlike())!=null) {
		   injectionEntityWrapper(entity,entityWrapper,"notlike");
	   }
	   if((entity=pagingandEntity.getIn())!=null) {
		   injectionEntityWrapper(entity,entityWrapper,"in");
	   }
	   return entityWrapper;
   }
   
   /**
    * EntityWrapper注入查询参数
    * @param entity 不同查询类型对应的实例
    * @param entityWrapper 
    * @param queryType 查询类型
    * @throws Exception 
    */
   private <E extends BaseModel<E>> void injectionEntityWrapper(E entity,EntityWrapper<E> entityWrapper,String queryType)throws Exception{
	   Method[] methods=entity.getClass().getDeclaredMethods();
	   String type;
	   boolean flag;
	   String column;
	   for(Method method:methods) { 
		   type=method.getGenericReturnType().toString();
		   flag=type.equals("class java.lang.Integer")||type.equals("class java.lang.String")||type.equals("class java.lang.Long"); //目前只做int，long，string三种查询支持，之后可根据功能需求扩展
		   if(flag&&method.getName().startsWith("get")&&method.invoke(entity)!=null) {
			   column=entity.getColumn(method.getName().substring(3, 4).toLowerCase()+method.getName().substring(4));
			   switch(queryType) {
			   		case "like":entityWrapper.like(column, method.invoke(entity).toString()); break;
			   		case "notlike":entityWrapper.notLike(column, method.invoke(entity).toString()); break;
			   		case "eq":entityWrapper.eq(column, type.equals("class java.lang.String")?method.invoke(entity).toString():Long.parseLong(method.invoke(entity).toString())); break;
			   		case "ne":entityWrapper.ne(column, type.equals("class java.lang.String")?method.invoke(entity).toString():Long.parseLong(method.invoke(entity).toString())); break;
			   		case "in":entityWrapper.in(column, method.invoke(entity).toString().split(",")); break;
			   }
		   }
	   }
   }
}
